package core.handler;

import com.sun.istack.internal.Nullable;

import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 单列结果集
 *
 * @author Feny
 * @date Created in 2022/7/12
 */
public class SingleColumnRowMapper<T> implements RowMapper<T> {
    private final Class<?> requiredType;

    public SingleColumnRowMapper(Class<?> requiredType) {
        this.requiredType = requiredType;
    }

    @Override
    @SuppressWarnings("unchecked")
    public T mapRow(ResultSet rs) throws SQLException {
        int count = rs.getMetaData().getColumnCount();
        if (count != 1) {
            throw new RuntimeException("期望结果集只有一列，实际有多列");
        }
        return (T) getResultSetValue(rs, 1, requiredType);
    }

    public static Object getResultSetValue(ResultSet rs, int index, @Nullable Class<?> requiredType) throws SQLException {
        Object value;

        if (String.class == requiredType) {
            return rs.getString(index);
        } else if (boolean.class == requiredType || Boolean.class == requiredType) {
            value = rs.getBoolean(index);
        } else if (byte.class == requiredType || Byte.class == requiredType) {
            value = rs.getByte(index);
        } else if (short.class == requiredType || Short.class == requiredType) {
            value = rs.getShort(index);
        } else if (int.class == requiredType || Integer.class == requiredType) {
            value = rs.getInt(index);
        } else if (long.class == requiredType || Long.class == requiredType) {
            value = rs.getLong(index);
        } else if (float.class == requiredType || Float.class == requiredType) {
            value = rs.getFloat(index);
        } else if (double.class == requiredType || Double.class == requiredType ||
                Number.class == requiredType) {
            value = rs.getDouble(index);
        } else if (BigDecimal.class == requiredType) {
            return rs.getBigDecimal(index);
        } else if (java.sql.Date.class == requiredType) {
            return rs.getDate(index);
        } else if (java.sql.Time.class == requiredType) {
            return rs.getTime(index);
        } else if (java.sql.Timestamp.class == requiredType || java.util.Date.class == requiredType) {
            return rs.getTimestamp(index);
        } else if (byte[].class == requiredType) {
            return rs.getBytes(index);
        } else if (Blob.class == requiredType) {
            return rs.getBlob(index);
        } else if (Clob.class == requiredType) {
            return rs.getClob(index);
        } else {
            String typeName = requiredType.getSimpleName();
            switch (typeName) {
                case "LocalDate":
                    return rs.getDate(index);
                case "LocalTime":
                    return rs.getTime(index);
                case "LocalDateTime":
                    return rs.getTimestamp(index);
            }
            return rs.getObject(index);
        }

        return (rs.wasNull() ? null : value);
    }
}
